home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 …ember: Reference Library / Apple Developer Reference Library (December 1999) (Disk 1).iso / pc / technical documentation / develop / develop issue 26 / develop issue 26 code / truffles - display mgr. / sprocket / sources / dialogwindow.cp < prev    next >
Encoding:
Text File  |  1996-01-02  |  8.1 KB  |  289 lines

  1. /*
  2.     File:        DialogWindow.cp
  3.  
  4.     Contains:    Implementation of a base class for Modeless Dialogs
  5.                 
  6.     Written by: Dave Falkenburg
  7.  
  8.     Copyright:    © 1993-1995 by Dave Falkenburg, all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.     
  12.          <8>     1/20/95    DRF        Deal with new menu command changes. Also fixed bug where we
  13.                                     weren’t disposing of TDialogWindows using DisposeDialog.
  14.          <7>    11/16/94    DRF        Added explicit #include <Traps.h> for latest universal headers.
  15.          <6>    11/12/94    DRF        Fix a bug in EventFilter method which returned false even if a
  16.                                     dialog item was hit.
  17.          <5>     11/8/94    DRF        We have better menu handling methods, so use them instead of the
  18.                                     old “DoEditMenu” method.
  19.          <3>    10/17/94    DRF         ItemHit is now a pure-virtual method. Fixed bugs in DoEditMenu.
  20.                                      Call StdFilterProc inside EventFilter to handle ok, cancel,
  21.                                     and I-beam cursor tracking.
  22.          <3>     9/27/94    DRF         AppLib.h is now Sprocket.h
  23.          <2>      9/9/94    DRF        Reordered headers and removed redundant #includes. Also fixed
  24.                                     constants in DoEditMenu.
  25.  */
  26.  
  27. #include "Sprocket.h"
  28. #include "DialogWindow.h"
  29. #include "StandardMenus.h"
  30. #include <Traps.h>
  31.  
  32. TDialogWindow::TDialogWindow(DialogType dialogType, DialogTemplateID theDialogTemplate)
  33.     {
  34.     fTemplateID = theDialogTemplate;
  35.     fIsDialogWindow = true;
  36.  
  37.     this->CreateWindow(((dialogType == kModalDialog) ? kModalWindow : kNormalWindow));
  38.     }
  39.  
  40.  
  41. WindowRef
  42. TDialogWindow::MakeNewWindow(WindowRef behindWindow)
  43.     {
  44.     return GetDialogWindow ( GetNewDialog(fTemplateID,nil, (WindowRef) behindWindow));
  45.     }
  46.  
  47.  
  48. Boolean
  49. TDialogWindow::Close(void)
  50.     {
  51. //    We have to do this in case all we are the last window open
  52. //    We don't want to leave the menu items enabled
  53.  
  54.     gMenuBar->EnableCommand ( cCut,            false );
  55.     gMenuBar->EnableCommand ( cCopy,        false );
  56.     gMenuBar->EnableCommand ( cPaste,        false );
  57.     gMenuBar->EnableCommand ( cClear,        false );
  58.     gMenuBar->EnableCommand ( cSelectAll,    false );
  59.  
  60.     return TWindow::Close();
  61.     }
  62.  
  63.  
  64. ////////////////////////////////////////////////////////////////////////////////////
  65. //
  66. //    EventFilter strategy for Dialog Window
  67. //
  68. //    Because of the need to patch and unpatch FrontWindow when calling IsDialogEvent
  69. //    and DialogSelect, only do these things when a Modless Dialog is the frontmost
  70. //    window. (e.g., it’s event filter is active)
  71. //
  72. //    NOTE: We always pass events through, except when an item has been hit.
  73. //
  74. //    You may be thinking that it is easier to just rewrite the Dialog Manager in
  75. //    this program. You’re probably right.
  76.  
  77. pascal    WindowRef    FrontWindowPatchForDialogs();
  78.  
  79.  
  80. pascal    WindowRef
  81. FrontWindowPatchForDialogs()
  82.     {
  83.     return TWindow::FrontNonFloatingWindow();
  84.     }
  85.  
  86.  
  87. #define    uppFrontWindowPatchProcInfo (kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(WindowRef))))
  88.  
  89. UniversalProcPtr FrontWindowPatchUPP
  90. = (UniversalProcPtr) NewRoutineDescriptor((ProcPtr) &FrontWindowPatchForDialogs,uppFrontWindowPatchProcInfo,GetCurrentISA());
  91.  
  92.  
  93. Boolean
  94. TDialogWindow::EventFilter(EventRecord *theEvent)
  95.     {
  96.     GrafPtr                oldPort;
  97.     UniversalProcPtr    oldFrontWindow = GetToolboxTrapAddress(_FrontWindow);
  98.     DialogRef            aDialog;
  99.     Boolean                eventHasBeenGobbled = false;
  100.     short                aDialogItem = 0;
  101.     short                oldWindowKind;
  102.     
  103.     //    Don’t snarf keypresses meant for menus
  104.     if ((theEvent->what == keyDown) && (theEvent->modifiers & cmdKey))
  105.         return false;
  106.  
  107.     GetPort(&oldPort);
  108.     SetGrafPortOfDialog ( GetDialogRef ());
  109.     
  110.     //    Patch in our version of FrontWindow so that IsDialogEvent will do the right
  111.     //    thing. DialogManager should check both frontmost floating and frontmost
  112.     //    non-floating windows, however we don’t support floating dialogs.
  113.     SetToolboxTrapAddress(FrontWindowPatchUPP,_FrontWindow);
  114.  
  115.     //    Jam the windowKind of our dialog window back to dialogKind so that the
  116.     //    Dialog Manager can recognize our window as a dialog window.
  117.     oldWindowKind = GetWindowKind(fWindow);
  118.     SetWindowKind(fWindow, dialogKind);
  119.     
  120.     
  121.     if (IsDialogEvent(theEvent))
  122.         {
  123.         //    It’s definitely a dialog event, so let the DialogMgr figure things out.
  124.         //
  125.         //    We first let StdFilterProc have a crack at it so that the default
  126.         //    and cancel buttons are properly processed (as well as automagic text
  127.         //    cursor tracking).
  128.         
  129.         //    If StdFilterProc didn’t find anything to do, go ahead and call
  130.         //    DialogSelect to figure out if the user did anything important.
  131.  
  132.         //    Isn’t this alot easier than what Inside Mac says to do?
  133.  
  134.         eventHasBeenGobbled = StdFilterProc( GetDialogRef (),theEvent,&aDialogItem);
  135.  
  136.     //    Give the window a chance to pre-process the event
  137.     //    This is useful for people who want to implement read-only text items (for example)
  138.     
  139.         if (eventHasBeenGobbled == false)
  140.             eventHasBeenGobbled = this->FilterDialogEvent ( theEvent, &aDialogItem );
  141.             
  142.     //    Let the dialog manager deal with the event
  143.         if (eventHasBeenGobbled == false)
  144.             eventHasBeenGobbled = DialogSelect(theEvent,&aDialog,&aDialogItem);
  145.         }
  146.  
  147.     //    Restore the windowKind
  148.     SetWindowKind(fWindow, oldWindowKind);
  149.  
  150.     //    Put FrontWindow back the way it really belongs
  151.     SetToolboxTrapAddress((UniversalProcPtr) oldFrontWindow,_FrontWindow);
  152.  
  153.     if (eventHasBeenGobbled)
  154.         {
  155.         this->ItemHit(aDialogItem);    //    Call user’s method to deal with a hit
  156.         eventHasBeenGobbled = true;
  157.         }
  158.         
  159.     SetPort(oldPort);
  160.     
  161.     return eventHasBeenGobbled;
  162.     }
  163.  
  164.  
  165. Boolean
  166. TDialogWindow::FilterDialogEvent(EventRecord */*theEvent*/, short *itemHit )
  167.     {
  168.     *itemHit = 0;
  169.     return false;    // Event not handled
  170.     }
  171.  
  172.  
  173. void
  174. TDialogWindow::Activate(Boolean activating)
  175.     {
  176.     EventRecord            fakeEvent;
  177.  
  178.     /*    (De)activates are NOT automagically handled because our floating
  179.      *    windows prevent real activate events from ever being generated
  180.      *    for any non-floaters windows.
  181.      *
  182.      *    Our strategy is to fool the dialog manager into thinking that
  183.      *    things are still fine by passing it a fake (de)activate event.
  184.      *
  185.      *    Luckily, we don’t have to patch FrontWindow to make DialogSelect
  186.      *    work for activate and update events.
  187.      */
  188.         
  189.     OSEventAvail(0,&fakeEvent);        //    Get an intialized, but otherwise empty event record
  190.     
  191.     fakeEvent.what = activateEvt;
  192.     fakeEvent.message = (unsigned long) GetDialogRef ();
  193.     if (activating)
  194.         fakeEvent.modifiers |= activeFlag;
  195.     else
  196.         fakeEvent.modifiers &= ~activeFlag;
  197.  
  198.     //    Pass event on to DialogSelect
  199.     
  200.     DialogRef    aDialog;
  201.     short        aDialogItem;
  202.     
  203.     (void) DialogSelect(&fakeEvent,&aDialog,&aDialogItem);
  204.     }
  205.     
  206.  
  207. void
  208. TDialogWindow::Draw(void)
  209.     {
  210.     //    Automagically handled by Dialog Manager when we are
  211.     //    the frontmost window, but not at other times because
  212.     //    we only set the windowKind to dialogKind inside our
  213.     //    EventFilter (which is only active when we are frontmost).
  214.     RgnHandle    update = NewRgn ();
  215.     GetWindowUpdateRgn ( fWindow, update );
  216.     UpdateDialog ( GetDialogRef (), update );
  217.     DisposeRgn ( update );
  218.     }
  219.     
  220.     
  221. void
  222. TDialogWindow::Click(EventRecord * /* anEvent */)
  223.     {
  224.     /*    The only time this method is called is to handle a click
  225.      *    when the dialog window isn’t frontmost. All other times,
  226.      *    DialogSelect will do everything for us.
  227.      *
  228.      *    If our dialog contains useritems with the ability to
  229.      *    be the source of a drag we’d need to start drag tracking
  230.      *    in here.
  231.      */
  232.      
  233.     this->Select();
  234.     }
  235.  
  236.     
  237. void
  238. TDialogWindow::AdjustMenusBeforeMenuSelection(void)
  239.     {
  240.     TEHandle    teh = GetDialogTextEdit ( GetDialogRef ());
  241.     Boolean        validSelection = teh != NULL && ( (*teh)->selStart != (*teh)->selEnd );
  242.     
  243.     gMenuBar->EnableCommand ( cCut,   validSelection );
  244.     gMenuBar->EnableCommand ( cCopy,  validSelection );
  245.     gMenuBar->EnableCommand ( cPaste, true );    // we really should check the scrap
  246.     gMenuBar->EnableCommand ( cClear, validSelection );
  247.  
  248.     gMenuBar->EnableCommand ( cSelectAll, teh != NULL );
  249.     }
  250.  
  251.  
  252. Boolean
  253. TDialogWindow::DoMenuCommand(MenuCommandID command)
  254.     {
  255.     DialogRef    theDialog =  GetDialogRef ();
  256.  
  257.     switch (command)
  258.         {
  259.         case    cUndo:
  260.             break;
  261.             
  262.         case    cCut:
  263.             DialogCut(theDialog);
  264.             return true;
  265.             
  266.         case    cCopy:
  267.             DialogCopy(theDialog); 
  268.             return true;
  269.             
  270.         case    cPaste:
  271.             DialogPaste(theDialog); 
  272.             return true;
  273.             
  274.         case    cClear:
  275.             DialogDelete(theDialog); 
  276.             return true;
  277.  
  278.         case    cSelectAll:
  279.             SelectDialogItemText ( theDialog, GetDialogKeyboardFocusItem ( theDialog ), 0, 32767 );
  280.             return true;
  281.  
  282.         default:
  283.             break;
  284.         }
  285.  
  286. //    If we don't handle it, then let the super-class handle it
  287.     return TWindow::DoMenuCommand ( command );
  288.     }
  289.